package com.fbt.transfer.app.driver.util;

import cn.hutool.core.text.CharSequenceUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.TimeZone;
import lombok.Getter;

/**
 * @author tuocoo
 */
public final class JsonUtil {

  @Getter
  private static ObjectMapper mapper;

  private JsonUtil() {
  }

  static {
    mapper = new ObjectMapper();
    mapper.setTimeZone(TimeZone.getTimeZone(ZoneId.ofOffset("GMT", ZoneOffset.of("+8"))));
    mapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
    mapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true);
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(
        DateTimeFormatter.ofPattern(Constants.DATE_YYYY_MM_DD_HH_MM_SS)));
    javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(
        DateTimeFormatter.ofPattern(Constants.DATE_YYYY_MM_DD)));
    javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(
        DateTimeFormatter.ofPattern(Constants.TIME_HH_MM_SS)));
    javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(
        DateTimeFormatter.ofPattern(Constants.DATE_YYYY_MM_DD_HH_MM_SS)));
    javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(
        DateTimeFormatter.ofPattern(Constants.DATE_YYYY_MM_DD)));
    javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(
        DateTimeFormatter.ofPattern(Constants.TIME_HH_MM_SS)));
    mapper.registerModule(javaTimeModule);
  }

  public static String toJson(Object object) {
    if (Objects.isNull(object)) {
      return Constants.EMPTY_STRING;
    }
    try {
      return mapper.writeValueAsString(object);
    } catch (JsonProcessingException e) {
      LogUtils.w("将{}对象解析成json失败:" + object);
    }
    return Constants.EMPTY_STRING;
  }

  public static <T> T fromJson2Generics(String json, TypeReference<T> valueTypeRef) {
    if (CharSequenceUtil.isBlank(json)) {
      return null;
    }
    try {
      return mapper.readValue(json, valueTypeRef);
    } catch (IOException e) {
      LogUtils.w("将json数据还原成JAVA对象" + valueTypeRef.getType().getTypeName());
    }
    return null;
  }

  public static <T> T toBean(String json, Class<T> t) {
    if (CharSequenceUtil.isBlank(json)) {
      return null;
    }
    try {
      return mapper.readValue(json, t);
    } catch (IOException e) {
      LogUtils.w(CharSequenceUtil.format("将json数据[{}],解析为{}失败", json, t.getTypeName()));
    }
    return null;
  }

  public static <T> List<T> toListBean(String json, Class<T> t) {
    return fromJson2Generics(json, new TypeReference<List<T>>() {
    });
  }
}
